home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
011
/
brutil.arc
/
DDU.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-05-10
|
27KB
|
1,491 lines
PAGE ,132
TITLE IBM-PC Dangerous Disk Utility ver 1.0, 26-Apr-88
; Based largely on the CHAIN program described below.
; DDU is written by Bruce Noblick, 185 Crestview Road, Columbus, Ohio 43202
; Phone: (614) 262-4564 evenings and weekends
;
; CHAIN was written by Steven Georgiades
;
; IBM-PC/XT File Chain Program
; Will respond with a list of the disk clusters that make up the file chain
; for the requested file.
;
; If you are using this program and find it of value, your
; contribution in any amount ($5.00 suggested) will be greatly
; appreciated. Makes checks payable to Steven M. Georgiades.
; Thank you.
;
; If you have any questions or comments about this or any other
; SMG program, call or write:
;
; Steven M. Georgiades
; 701-H South Hayward Street
; Anaheim, CA 92804
; (714) 826-9549
;
IF1
INCLUDE OPTMAC.LIB
ENDIF
GENOPT BFOPAMUV
CODE SEGMENT
ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE
ORG 5CH
FCB LABEL BYTE
ORG 80H
PARAM LABEL BYTE
ORG 100H
CHAIN: JMP BEGIN
ANDSTR DB ", $"
ORMSG DB 'Stack Overrun xxxxx',13,10,'$'
ME1MSG DB 'is already unmarked (free)',13,10,'$'
ME2MSG DB 'is already marked bad',13,10,'$'
ME3MSG DB 'is in use by a file',13,10,'$'
ME4MSG DB 'is reserved',13,10,'$'
UMMSG DB 'has been unmarked (freed)',13,10,'$'
MKMSG DB 'has been marked bad',13,10,'$'
VERMSG DB 'Verify marked xxxxx clusters bad',13,10,'$'
VEREM1 DB 'Sector xxxxx of system area is bad',13,10,'$'
BDMSG1 DB 'Bad $'
FRMSG1 DB 'Free $'
ALMSG1 DB 'Allocated$'
FRMSG2 DB ' Clusters on drive x:',13,10,10,'$'
FRMSG3 DB 13,10,10
FRMSG4 DB 'Total Clusters = xxxxx',13,10,10
FRMSG5 DB 'Total Bytes = xxxxxxxx',13,10,'$'
CHMSG1 DB "The Chain for $"
CHMSG2 DB " is:",13,10,10,"$"
CHMSG3 DB 13,10,10
CHMSG4 DB "Total Clusters in File = XXXXX",13,10,10
CHMSG5 DB "Physical File Length = XXXXXXXX",13,10
CHMSG6 DB "Logical File Length = XXXXXXXX ("
PERCENT DB " 0.00% Waste)",13,10,"$"
CLSTSTR DB "XXXXX$"
PCT100 DB "100.0"
SPECERR DB "Invalid File or Path Specification",7,": $"
DTTAB LABEL BYTE
DW 512
DB 1
DW 1
DB 2
DW 224
DW 2400
DB 0F9H
DW 7
DW 15
DW 2
DW 0
DW 512
DB 1
DW 1
DB 2
DW 64
DW 360
DB 0FCH
DW 2
DW 9
DW 1
DW 0
DW 512
DB 2
DW 1
DB 2
DW 112
DW 720
DB 0FDH
DW 2
DW 9
DW 2
DW 0
DW 512
DB 1
DW 1
DB 2
DW 64
DW 320
DB 0FEH
DW 1
DW 8
DW 1
DW 0
DW 512
DB 2
DW 1
DB 2
DW 112
DW 640
DB 0FFH
DW 1
DW 8
DW 2
DW 0
DTMSG DB 'Using FAT ID byte to construct disk type table',13,10,'$'
TERRMSG DB 'Media Byte xxxxx not supported',7,13,10,'$'
PARMSG DB 'Parameters for drive x:',13,10,10
PARMSG17 DB 'OEM Name: xxxxxxxx',13,10
PARMSG3 DB 'Bytes/Sector: xxxxx',13,10
PARMSG2 DB 'Sectors/Cluster: xxxxx',13,10
PARMSG6 DB 'Reserved Sectors: xxxxx',13,10
PARMSG5 DB 'Copies/FAT: xxxxx',13,10
PARMSG7 DB 'Entries/Directory: xxxxx '
PARMSG8 DB '(Sectors/Directory: xxxxx)',13,10
PARMSG1 DB 'Sectors/Media: xxxxx '
PARMSG18 DB '(Bytes/Media: xxxxxxxx)',13,10
PARMSG16 DB 'Media Byte: xxxxx',13,10
PARMSG4 DB 'Sectors/FAT: xxxxx',13,10
PARMSG11 DB 'Sectors/Track: xxxxx',13,10
PARMSG12 DB 'Sides: xxxxx '
PARMSG13 DB '(Tracks: xxxxx)',13,10
PARMSG14 DB 'Hidden sectors: xxxxx',13,10
PARMSG9 DB '(First Data Sector: xxxxx)',13,10
PARMSG10 DB '(Highest cluster: xxxxx) '
PARMSG19 DB '(Bytes/Data: xxxxxxxx)',13,10
PARMSG15 DB '(Ignored Sectors: xxxxx)'
CRLF DB 13,10,"$"
READERR DB 'Error Reading Drive x:',7,13,10,'$'
CLSTMSG DB 'Cluster xxxxx $'
ONERMSG DB 'is owned by $'
BADMSG DB 'is marked as bad',13,10,'$'
FREEMSG DB 'is not in use by any file',13,10,'$'
INVALID DB 'does not exist!',7,13,10,'$'
LOSTMSG DB 'appears to be lost!',7,13,10,'$'
RESVMSG DB 'is reserved',13,10,'$'
CLSTSEC DW ?
TOTCLST DW ?
DIR_LEN DW ?
DIRBUF DW ?
DIRSEC DW ?
DRIVE DB ?
EOF DW 0FF8H
BAD DW ?
OPFLAG DB 0
FATCOP DB ?
FATSEC DW ?
FATSIZE DB 3
FNAME DB 13 DUP(0)
PREV DW ?
RANGE DB 0
SECSIZE DW ?
CLUST DW ?
RDIRLEN DW ?
NEWSTK DW 0
NEXTOP DW ?
SIZLSB DW ?
SIZMSB DW ?
STRTSEC DW ?
FSPEC DB 80 DUP(0)
BEGIN: MOV AH,19H ; Get Default Drive
INT 21H
MOV DRIVE,AL ; and Save
MOV SI,OFFSET PARAM ; Set up Pointer to Parameter
LODSB ; Read Parameter Length
CBW
MOV BX,AX
MOV BYTE PTR [SI+BX],0 ; Terminate Parameter String
CALL STRIP
JNC BEGIN2
JMP ERROR
BEGIN2: MOV NEXTOP,SI
MOV AL,DRIVE ; Read Boot Record
MOV CX,1
MOV DX,0
MOV BX,OFFSET FATBUF
INT 25H
JNC BOOT_OK
JMP RDERROR
BOOT_OK:
POPF
CMP BYTE PTR FATBUF,0E9H
JZ OKTYPE
CMP BYTE PTR FATBUF,0EBH
JZ OKTYPE
MOV AL,DRIVE
MOV CX,1
MOV DX,CX
MOV BX,OFFSET FATBUF+128
INT 25H
JNC CHKTYP
JMP RDERROR
CHKTYP: POPF
MOV AL,BYTE PTR FATBUF+128
CMP AL,BYTE PTR FATBUF+21
JZ OKTYPE
MOV SI,OFFSET DTTAB
MOV CX,5
TSTTYP: CMP AL,10[SI]
JZ MOVTYP
ADD SI,19
LOOP TSTTYP
MOV AL,-9[SI]
MOV DI,OFFSET TERRMSG+16
CALL DEC5OUT
CALL STRIP0
MOV DX,OFFSET TERRMSG
JMP ERROUT
MOVTYP: MOV DI,OFFSET FATBUF+3
MOV AX,' '
MOV CX,4
REP STOSW
MOV CX,10
REP MOVSW
MOV DX,OFFSET DTMSG
CALL DOS9
OKTYPE: MOV AX,FATBUF+11 ; Read Sector Size
MOV SECSIZE,AX ; and Save
MOV AL,BYTE PTR FATBUF+13 ; Read Sectors per Cluster
XOR AH,AH
MOV CLSTSEC,AX ; and Save
MOV CX,FATBUF+14 ; Read # of Reserved Sectors
MOV AL,BYTE PTR FATBUF+16 ; Read # of FAT's
MOV BX,FATBUF+22 ; Read Sectors per FAT
MOV FATSEC,BX
MOV FATCOP,AL
MUL BX ; Calculate Total FAT Sectors
ADD CX,AX ; Add to Reserved Sectors
MOV AX,FATBUF+17 ; Read Number of DIR Entries
MOV RDIRLEN,AX
MOV DIR_LEN,AX
PUSH CX ; Calculate DIR Sectors
MOV CL,5
SHL AX,CL
POP CX
MOV BX,SECSIZE
XOR DX,DX
DIV BX
ADD DX,-1
ADC AX,0
MOV DIRSEC,AX ; Save DIR Sectors
ADD CX,AX ; Add DIR Sectors to Reserved
MOV STRTSEC,CX ; Save in STRTSEC
MOV AX,FATSEC ; Calculate FAT Buffer Size
MOV BX,SECSIZE
MUL BX
MOV BX,AX
ADD AX,OFFSET FATBUF ; Get DIR Buffer Pointer
MOV DIRBUF,AX
MOV AX,FATBUF+19 ; Read Total Sectors on Media
SUB AX,CX ; Calculate Total Data Clusters
MOV BX,CLSTSEC
XOR DX,DX
DIV BX
INC AX
MOV TOTCLST,AX
CMP AX,4080 ; If Necessary, Adjust FAT Size
JL FAT_OK
MOV FATSIZE,4
MOV EOF,0FFF8H
FAT_OK: CMP OPFLAG,POPT
JZ NO_FAT
JMP FAT_OK1
NO_FAT: MOV SI,OFFSET FATBUF+3
MOV DI,OFFSET PARMSG17+17
MOV CX,4
REP MOVSW
LODSW
MOV DI,OFFSET PARMSG3+25
CALL DEC5OUT
CALL STRIP0
LODSB
XOR AH,AH
MOV DI,OFFSET PARMSG2+25
CALL DEC5OUT
CALL STRIP0
LODSW
MOV DI,OFFSET PARMSG6+25
CALL DEC5OUT
CALL STRIP0
LODSB
XOR AH,AH
MOV DI,OFFSET PARMSG5+25
CALL DEC5OUT
CALL STRIP0
LODSW
MOV DI,OFFSET PARMSG7+25
CALL DEC5OUT
CALL STRIP0
LODSW
MOV BX,AX
MOV DI,OFFSET PARMSG1+25
CALL DEC5OUT
CALL STRIP0
MOV AX,BX
MUL SECSIZE
MOV DI,OFFSET PARMSG18+25
CALL DEC8OUT
CALL STRIP0
LODSB
XOR AH,AH
MOV DI,OFFSET PARMSG16+25
CALL DEC5OUT
CALL STRIP0
LODSW
MOV DI,OFFSET PARMSG4+25
CALL DEC5OUT
CALL STRIP0
LODSW
MOV DI,OFFSET PARMSG11+25
CALL DEC5OUT
CALL STRIP0
LODSW
MOV DI,OFFSET PARMSG12+25
CALL DEC5OUT
CALL STRIP0
LODSW
MOV DI,OFFSET PARMSG14+25
CALL DEC5OUT
CALL STRIP0
MOV AX,DIRSEC
MOV DI,OFFSET PARMSG8+25
CALL DEC5OUT
CALL STRIP0
MOV AX,STRTSEC
MOV DI,OFFSET PARMSG9+25
CALL DEC5OUT
CALL STRIP0
MOV AX,TOTCLST
MOV BX,AX
MOV DI,OFFSET PARMSG10+25
CALL DEC5OUT
CALL STRIP0
MOV AX,BX
DEC AX
MUL CLSTSEC
MUL SECSIZE
MOV DI,OFFSET PARMSG19+25
CALL DEC8OUT
CALL STRIP0
MOV AX,FATBUF+24
MUL FATBUF+26
MOV BX,AX
MOV AX,FATBUF+19
ADD AX,FATBUF+28
DIV BX
OR DX,DX
JZ NO_ADD2
INC AX
JMP SHORT NO_ADD3
NO_ADD2:
MOV DX,BX
NO_ADD3:
MOV DI,OFFSET PARMSG13+25
CALL DEC5OUT
CALL STRIP0
MOV AX,BX
SUB AX,DX
MOV DI,OFFSET PARMSG15+25
CALL DEC5OUT
CALL STRIP0
MOV DX,OFFSET PARMSG
JMP CC_OK_3
FAT_OK1:
MOV AL,DRIVE ; Read FAT
MOV CX,FATSEC
MOV DX,1
MOV BX,OFFSET FATBUF
INT 25H
JNC FAT_OK2
JMP RDERROR
FAT_OK2:
POPF
MOV AX,EOF
DEC AX
MOV BAD,AX
CMP OPFLAG,BOPT
JZ GOTB
CMP OPFLAG,FOPT
JZ GOTF
CMP OPFLAG,AOPT
JZ GOTA
CMP OPFLAG,MOPT
JNZ NOTM
JMP MARKIT
NOTM:
CMP OPFLAG,UOPT
JNZ NOTU
JMP UNMARK
NOTU:
CMP OPFLAG,VOPT
JNZ NOTV
JMP VERIFY
NOTV:
CMP OPFLAG,OOPT
JZ RDROOT
CMP OPFLAG,0
JZ RDROOT
JMP ERROR
GOTB: MOV DX,OFFSET BDMSG1
JMP SHORT GOTMSG
GOTF: MOV DX,OFFSET FRMSG1
JMP SHORT GOTMSG
GOTA: MOV DX,OFFSET ALMSG1
GOTMSG: CALL DOS9
MOV DX,OFFSET FRMSG2
CALL DOS9
MOV BX,2
XOR CX,CX
CL1: CALL TESTCL
JNZ CL1
MOV AX,BX
DEC AX
MOV PREV,AX
CALL OUT_CLST
INC CX
CL1D: CALL TESTCL
JNZ CL1D
MOV AX,BX
DEC AX
DEC AX
INC CX
CMP AX,PREV
PUSHF
INC AX
POPF
JNE CL1G
MOV RANGE,-1
JMP SHORT CL1I
CL1G: CALL SENDEM
MOV AX,BX
DEC AX
CALL OUT_CLST
CL1I: MOV AX,BX
DEC AX
MOV PREV,AX
JMP CL1D
CL1J: JMP FINDSK
RDROOT: CMP OPFLAG,OOPT
JNZ RDROOT2
CALL OWNER
RDROOT2:
CALL GETROOT
MOV SI,OFFSET FSPEC+3 ; Point to First Element of Path
NEXT_FLD:
MOV DI,OFFSET FNAME ; Point to FileName Buffer
NEXTCHAR:
LODSB ; Copy Path Element to FileName
CMP AL,'\' ; until '\' or nul
JE GOT_DIR
STOSB
OR AL,AL
JE GOT_FNM
JMP NEXTCHAR
GOT_DIR:
MOV AL,0 ; If '\', Read Subdirectory
STOSB
CALL READDIR
JNC NEXT_FLD ; If No Error, Get Next Dir
JMP ERROR ; Else Flag Error
GOT_FNM:
CALL SRCHFILE ; Read File DIR Info
JNC NOERR3
JMP ERROR ; If Error, Say So
NOERR3: MOV AX,[BX+28] ; Read File Length
MOV SIZLSB,AX
MOV DX,[BX+30]
MOV SIZMSB,DX
MOV DI,OFFSET CHMSG6+31 ; Convert to ASCII
CALL DEC8OUT ; Strip Off Leading Zeroes
CALL STRIP0
MOV DX,OFFSET CHMSG1 ; Output FileSpec Message
CALL DOS9
MOV DX,OFFSET FSPEC
CALL ALTDOS9
MOV DX,OFFSET CHMSG2
CALL DOS9
MOV BX,[BX+26] ; Read Starting Cluster Number
XOR CX,CX ; Cluster Count = 0
OR BX,BX ; If Start Cluster = 0, Done
JZ LASTCLST
MOV AX,BX ; Output First Cluster Number
CALL OUT_CLST
MOV PREV,BX ; Previous Cluster = First
INC CX ; Cluster Count = 1
CALL NEXTCLST ; Get Next Cluster Number
CMP BX,EOF ; If Last, Skip
JNB LASTCLST
CLSTLOOP:
INC CX ; Increment Cluster Count
MOV AX,PREV ; If Cluster is Previous + 1,
INC AX
CMP AX,BX
JNE CLSTOUT
MOV RANGE,-1 ; Set Range Flag
JMP SHORT NEXTONE
CLSTOUT:
CALL SENDEM
CALL OUT_CLST
NEXTONE:
MOV PREV,BX ; Previous = Current
CALL NEXTCLST ; Get Next Cluster Number
CMP BX,EOF ; If Not EOF, Repeat
JB CLSTLOOP
FINDSK: CMP RANGE,0 ; If Range Flag is Set,
JE LASTCLST
MOV AH,2 ; Output " - "
MOV DL,'-'
INT 21H
MOV AX,PREV ; Output Last Cluster of Range
CALL OUT_CLST
LASTCLST:
CMP OPFLAG,0
JNZ CLSTCNT
MOV AX,SIZMSB ; If Size = 0, 100% Waste
OR AX,SIZLSB
JNZ NOT_ZERO
MOV SI,OFFSET PCT100
MOV DI,OFFSET PERCENT
PUSH CX
MOV CX,5
REP MOVSB
POP CX
JMP SHORT CLSTCNT
NOT_ZERO:
MOV AX,SECSIZE ; Calculate Percent Waste
MOV BX,CLSTSEC
MUL BX
MOV BX,AX
MUL CX
SUB AX,SIZLSB
MOV DX,100
MUL DX
DIV BX
PUSH DX
XOR DX,DX
DIV CX
PUSH DX
MOV DI,OFFSET PERCENT+2 ; Convert Percent to ASCII
CALL DEC2OUT
CALL STRIP0
POP AX
MUL BX
POP DI
ADD AX,DI
ADC DX,0
DIV CX
MOV DX,100
MUL DX
DIV BX
MOV DI,OFFSET PERCENT+5
CALL DEC2OUT
CLSTCNT:
MOV AX,CX ; Convert Cluster Count to ASCII
MOV DI,OFFSET CHMSG4+31
CMP OPFLAG,0
JZ CC_OK
MOV DI,OFFSET FRMSG4+22
CC_OK: CALL DEC5OUT
CALL STRIP0 ; Strip Off Leading Zeroes
MOV AX,CLSTSEC ; Calculate Physical File Size
MUL CX
MOV CX,SECSIZE
MUL CX
MOV DI,OFFSET CHMSG5+31 ; Convert to ASCII
CMP OPFLAG,0
JZ CC_OK_2
MOV DI,OFFSET FRMSG5+22 ; Convert to ASCII
CC_OK_2:
CALL DEC8OUT
CALL STRIP0 ; Strip Off Leading Zeroes
MOV DX,OFFSET CHMSG3 ; Output Trailer Message
CMP OPFLAG,0
JZ CC_OK_3
MOV DX,OFFSET FRMSG3 ; Output Trailer Message
CC_OK_3:
CALL DOS9
MOV SI,NEXTOP
CALL STRIP
JC CC_OK_4
JMP BEGIN2
CC_OK_4:
MOV AX,4C00H ; Exit to DOS
INT 21H
TESTCL: CMP BX,TOTCLST
JA TC3
PUSH BX
CALL NEXTCLST
MOV AX,BX
POP BX
INC BX
CMP OPFLAG,BOPT
JZ TC1
CMP OPFLAG,FOPT
JZ TC1A
OR AX,AX
JZ TC0
CMP AX,BAD
JZ TC0
CMP AX,AX
JMP SHORT TC2
TC0: SUB AX,AX
INC AX
JMP SHORT TC2
TC1A: OR AX,AX
JMP SHORT TC2
TC1: CMP AX,BAD
TC2: RET
TC3: JMP CL1J
ERROR: MOV DX,OFFSET SPECERR ; Output Error Message
CALL DOS9
MOV DX,OFFSET PARAM ; Output FileSpec
CALL ALTDOS9
JMP CRLFX
OWNER: CALL GETCLST
CALL NEXTCLST
OR BX,BX
JNZ NOT_FREE
MOV DX,OFFSET FREEMSG
JMP CC_OK_3
NOT_FREE:
MOV AX,EOF
CMP BX,AX
JAE CLSTGOOD
DEC AX
CMP BX,AX
JNE NOT_BAD
MOV DX,OFFSET BADMSG
JMP CC_OK_3
NOT_BAD:
SUB AX,7
CMP BX,AX
JB CLSTGOOD
MOV DX,OFFSET RESVMSG
JMP CC_OK_3
RDERROR:
POPF
MOV AL,DRIVE
ADD AL,'A'
MOV READERR+20,AL
MOV DX,OFFSET READERR
ERROUT: CALL DOS9
MOV AX,4C01H ; Exit to DOS
INT 21H
CLSTGOOD:
MOV AX,CLUST
CLSTBACK:
MOV BX,AX
CALL PREVCLST
OR AX,AX
JNZ CLSTBACK
MOV CLUST,BX
CALL GETROOT
SUB BX,BX
MOV NEWSTK,BX
CALL PUSHBX
LOOK1: CALL SRCHCLST
JNC FOUND
MOV SI,DIRBUF
MOV CX,DIR_LEN
LOOK2: CALL FINDDIR
JC LOOK3
MOV BX,26[SI]
CALL PUSHBX
ADD SI,32
LOOP LOOK2
LOOK3: CALL POPBX
JZ BADCLST
CALL GETADIR
JMP LOOK1
BADCLST:
MOV DX,OFFSET LOSTMSG
JMP CC_OK_3
FOUND: SUB BX,BX
MOV NEWSTK,BX
CALL PUSHBX
MOV BX,CLUST
CALL PUSHBX
MOV SI,DIRBUF
CMP BYTE PTR [SI],'.'
JNZ GOTEM
MOV BX,26[SI]
CALL PUSHBX
BACKTRACK:
MOV BX,58[SI]
CALL PUSHBX
JZ ENDBACK
PUSH SI
CALL GETADIR
POP SI
JMP BACKTRACK
ENDBACK:
CALL POPBX
CALL GETROOT
GOTEM: MOV DI,OFFSET FSPEC+2
UNDO: CALL POPBX
INT 3
JZ UNDONE
MOV CLUST,BX
CALL SRCHCLST
MOV SI,OFFSET FNAME
MOV AL,'\'
STOSB
CALL MOVSTR
CALL POPBX
CALL PUSHBX
JZ UNDONE
PUSH DI
MOV BX,CLUST
CALL GETADIR
POP DI
DEC DI
JMP UNDO
UNDONE: MOV DX,OFFSET ONERMSG
CALL DOS9
MOV DX,OFFSET FSPEC
CALL ALTDOS9
CRLFX: MOV DX,OFFSET CRLF
DOS9: MOV AH,9
INT 21H
RET
ALTDOS9:
PUSH SI
PUSH DX
MOV SI,DX
AD1: LODSB
OR AL,AL
JZ AD2
MOV DL,AL
MOV AH,2
INT 21H
JMP AD1
AD2: POP DX
POP SI
RET
MARKIT: CALL GETCLST
CALL NEXTCLST
OR BX,BX
JZ MARKCOM
MARKERR:
OR BX,BX
JZ ME1
MOV AX,BAD
CMP BX,AX
JE ME2
JA ME3
SUB AX,7
CMP BX,AX
JB ME3
MOV DX,OFFSET ME4MSG
JMP CC_OK_3
ME1: MOV DX,OFFSET ME1MSG
JMP CC_OK_3
ME2: MOV DX,OFFSET ME2MSG
JMP CC_OK_3
ME3: MOV DX,OFFSET ME3MSG
JMP CC_OK_3
UNMARK: CALL GETCLST
CALL NEXTCLST
CMP BX,BAD
JNZ MARKERR
MARKCOM:
MOV AX,BX
MOV BX,CLUST
XOR AX,BAD
PUSH AX
CALL SETCLST
CALL WRT_FAT
POP AX
OR AX,AX
MOV DX,OFFSET UMMSG
JZ UMMCOM
MOV DX,OFFSET MKMSG
UMMCOM: JMP CC_OK_3
VERIFY: MOV OPFLAG,0
MOV AL,DRIVE
MOV CX,STRTSEC
MOV DX,0
MOV BX,DIRBUF
VERLP1: PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV CX,1
INT 25H
JC VERER1
POPF
POP DX
POP CX
POP BX
POP AX
INC DX
LOOP VERLP1
MOV BX,2
MOV CX,0
VERLP2: CMP BX,TOTCLST
JA VERLP2X
CLC
PUSH BX
MOV DI,DIRBUF
CALL READCLST
POP BX
JC VERMRK
VERNXT: INC BX
JMP VERLP2
VERER1: MOV AX,DX
MOV DI,OFFSET VEREM1+12
CALL DEC5OUT
CALL STRIP0
MOV DX,OFFSET VEREM1
ADD SP,10
JMP CC_OK_3
VERLP2X:
OR CX,CX
JZ VERLP2Y
PUSH CX
CALL WRT_FAT
POP CX
VERLP2Y:
MOV AX,CX
MOV DI,OFFSET VERMSG+19
CALL DEC5OUT
CALL STRIP0
MOV DX,OFFSET VERMSG
JMP CC_OK_3
VERMRK: MOV CLUST,BX
MOV AX,BX
MOV DI,OFFSET CLSTMSG+13
CALL DEC5OUT
CALL STRIP0
MOV DX,OFFSET CLSTMSG
CALL DOS9
CALL NEXTCLST
OR BX,BX
JNZ VERERR
MOV AX,BAD
MOV BX,CLUST
CALL SETCLST
INC CX
MOV DX,OFFSET MKMSG
CALL DOS9
JMP VERNXT
VERERR: MOV AX,BAD
CMP BX,AX
JE VE2
JA VE3
SUB AX,7
CMP BX,AX
JB VE3
MOV DX,OFFSET ME4MSG
VE4: CALL DOS9
MOV BX,CLUST
JMP VERNXT
VE2: MOV DX,OFFSET ME2MSG
JMP VE4
VE3: MOV DX,OFFSET ME3MSG
JMP VE4
WRT_FAT:
MOV AL,DRIVE
MOV CX,FATSEC
MOV DX,1
MOV AH,FATCOP
MOV BX,OFFSET FATBUF
FATLOOP:
PUSH AX
PUSH BX
PUSH CX
PUSH DX
INT 26H
POPF
POP DX
POP CX
POP BX
POP AX
ADD DX,CX
DEC AH
JNZ FATLOOP
MOV AH,13
INT 21H
RET
SETCLST:
PUSH BX
CMP FATSIZE,3
JZ SETC_12
SHL BX,1
MOV FATBUF[BX],AX
JMP SHORT SETC_DONE
SETC_12:
PUSH CX
MOV CX,BX
SHL CX,1
ADD BX,CX
SHR BX,1
MOV CX,0F000H
JNC SETC_OK
MOV CL,4
SHL AX,CL
MOV CX,0FH
SETC_OK:
AND FATBUF[BX],CX
OR FATBUF[BX],AX
POP CX
SETC_DONE:
POP BX
RET
GETCLST:
MOV SI,OFFSET FSPEC+3
MOV OPFLAG,0
OWNER1: MOV DI,SI
OWNER2: LODSB
CMP AL,'\'
JZ OWNER1
OR AL,AL
JNZ OWNER2
MOV SI,DI
CALL GET_WORD
MOV CLUST,DX
MOV BX,DX
MOV AX,BX
MOV DI,OFFSET CLSTMSG+13
CALL DEC5OUT
CALL STRIP0
MOV DX,OFFSET CLSTMSG
CALL DOS9
CMP BX,TOTCLST
JA CLSTBAD
CMP BX,2
JB CLSTBAD
RET
CLSTBAD:
MOV DX,OFFSET INVALID
JMP CC_OK_3
GETROOT:
MOV AL,DRIVE ; Read Root Directory
MOV CX,DIRSEC
MOV DX,STRTSEC
SUB DX,CX
MOV BX,DIRBUF
INT 25H
POPF
MOV AX,RDIRLEN
MOV DIR_LEN,AX
RET
SENDEM: CMP RANGE,0 ; Else
JE SE1 ; If Range Flag is Set,
MOV AH,2 ; Output " - "
MOV DL,'-'
INT 21H
MOV AX,PREV ; Output Last Clstr in Range
CALL OUT_CLST
MOV RANGE,0 ; Reset Range Flag
SE1: MOV DX,OFFSET ANDSTR ; Output ", "
CALL DOS9
MOV AX,BX ; Output Cluster Number
RET
SRCHFILE:
PUSH AX ; Save Register
PUSH CX
PUSH DI
PUSH SI
CMP FNAME,'.' ; If Filename Starts with '.',
JNE SRCHFIL2
MOV SI,OFFSET FNAME ; Copy Filename to FCB
MOV DI,OFFSET FCB+1
MOV CX,11
SRCHFIL1:
LODSB
STOSB
OR AL,AL
LOOPNZ SRCHFIL1
INC CX ; and Pad With Spaces
DEC DI
MOV AL,' '
REP STOSB
JMP SHORT SRCHFIL3
SRCHFIL2:
MOV AX,2900H ; Else Parse Filename
MOV SI,OFFSET FNAME
MOV DI,OFFSET FCB
INT 21H
SRCHFIL3:
MOV DI,OFFSET FCB+1 ; Point to Filename in FCB
MOV SI,DIRBUF ; Point to Start of DIRBUF
MOV CX,DIR_LEN ; Load DIR Length
JCXZ SRCHFIL5 ; If Zero, Not Found
SRCHFIL4:
PUSH CX ; Save Registers
PUSH DI
PUSH SI
MOV CX,11 ; Compare Filename
REPE CMPSB
POP SI ; Restore Registers
POP DI
POP CX
JE SRCHFIL6 ; If Match, Found
ADD SI,32 ; Else Next DIR Entry
LOOP SRCHFIL4 ; and Repeat
SRCHFIL5:
STC ; Set Error Flag
JMP SHORT SRCHFIL7 ; Done
SRCHFIL6:
MOV BX,SI ; Set Pointer to DIR Entry
CLC ; Clear Error Flag
SRCHFIL7:
POP SI ; Restore Registers
POP DI
POP CX
POP AX
RET ; Done
READDIR:
PUSH CX ; Save Registers
PUSH DI
PUSH SI
CALL SRCHFILE ; Search for DIR
JC READDIR3 ; If Not Found, Error
MOV BX,[BX+26] ; Get Starting Cluster Number
OR BX,BX ; If Start Cluster = 0, Error
STC
JZ READDIR3
CALL GETADIR
READDIR3:
POP SI ; Restore Registers
POP DI
POP CX
RET ; Done
GETADIR:
MOV DIR_LEN,0 ; DIR Length = 0
MOV AX,SECSIZE ; Calculate DIR Entries/Cluster
MUL CLSTSEC
MOV CL,5
SHR AX,CL
MOV CX,AX
MOV DI,DIRBUF ; Point to DIR Buffer
READLOOP:
CALL READCLST ; Read Cluster
ADD DIR_LEN,CX ; Increment DIR Length
CMP BX,EOF ; If Not Last Cluster,
JB READLOOP ; Get Next Cluster
RET
PUSHBX: CMP NEWSTK,4096
JZ PPBXR
PUSH AX
MOV AX,BX
MOV BX,NEWSTK
INC NEWSTK
ADD BX,BX
MOV TABLE[BX],AX
MOV BX,AX
POP AX
PPBX: OR BX,BX
RET
PPBXR: MOV AX,NEWSTK
MOV DI,OFFSET ORMSG+14
CALL DEC5OUT
CALL STRIP0
MOV DX,OFFSET ORMSG
JMP ERROUT
POPBX: CMP NEWSTK,0
JZ PPBXR
DEC NEWSTK
MOV BX,NEWSTK
ADD BX,BX
MOV BX,TABLE[BX]
JMP PPBX
FINDDIR:
JCXZ FINDDIR4
FINDDIR2:
CMP BYTE PTR [SI],'.'
JE FINDDIR3
CMP BYTE PTR [SI],0E5H
JE FINDDIR3
CMP BYTE PTR [SI],0
JE FINDDIR4
TEST BYTE PTR [SI+11],10H
CLC
JNZ FINDDIR5
FINDDIR3:
ADD SI,32
LOOP FINDDIR2
FINDDIR4:
STC
FINDDIR5:
RET
SRCHCLST:
PUSH AX
PUSH CX
PUSH DI
PUSH SI
MOV SI,DIRBUF
MOV CX,DIR_LEN
JCXZ SRCHCLS3
MOV BX,CLUST
SRCHCLS1:
CMP BYTE PTR [SI],'.'
JE SRCHCLS2
CMP BYTE PTR [SI],0E5H
JE SRCHCLS2
CMP BYTE PTR [SI],0
JE SRCHCLS3
CMP BX,[SI+26]
JE SRCHCLS4
SRCHCLS2:
ADD SI,32
LOOP SRCHCLS1
SRCHCLS3:
STC
JMP SHORT SRCHCLS5
SRCHCLS4:
MOV DI,OFFSET FNAME
CALL UNPARSE
CLC
SRCHCLS5:
POP SI
POP DI
POP CX
POP AX
RET
PREVCLST:
PUSH BX
PUSH CX
PUSH DX
MOV DX,BX
MOV CX,TOTCLST
DEC CX
PREVCLS1:
MOV BX,CX
INC BX
CALL NEXTCLST
CMP BX,DX
LOOPNE PREVCLS1
JNE PREVCLS2
ADD CX,2
PREVCLS2:
MOV AX,CX
POP DX
POP CX
POP BX
RET
UNPARSE:
PUSH CX
PUSH DI
PUSH SI
MOV CX,8
CALL UNPARSE1
MOV AL,'.'
STOSB
POP SI
PUSH SI
ADD SI,8
MOV CX,3
CALL UNPARSE1
CMP CX,3
JNE UNPARSE5
DEC DI
UNPARSE5:
MOV AL,0
STOSB
POP SI
POP DI
POP CX
RET
UNPARSE1:
LODSB
CMP AL,' '
JE UNPARSE2
STOSB
LOOP UNPARSE1
UNPARSE2:
RET
MOVSTR: LODSB
STOSB
OR AL,AL
JNZ MOVSTR
RET
GET_WORD:
PUSH BX
XOR DX,DX
GET_WRD1:
LODSB
CMP AL,'0'
JB GET_WRD2
CMP AL,'9'
JA GET_WRD2
SUB AL,'0'
CBW
MOV BX,AX
MOV AX,10
MUL DX
ADD AX,BX
MOV DX,AX
JMP GET_WRD1
GET_WRD2:
DEC SI
POP BX
RET
READCLST:
PUSH AX ; Save Registers
PUSH CX
PUSH DX
PUSH BX ; Save Registers
PUSH DI
MOV AX,BX ; Calculate Absolute Sector #
SUB AX,2
MOV CX,CLSTSEC
MUL CX
ADD AX,STRTSEC
MOV DX,AX
MOV AL,DRIVE
MOV BX,DI ; Read Cluster
INT 25H
JC RCERR
POPF
POP DI ; Restore Registers
POP BX
CALL NEXTCLST ; Get Next Cluster Number
MOV AX,CLSTSEC ; Increment Buffer Pointer
MUL SECSIZE
ADD DI,AX
JMP SHORT RCCOM
RCERR: POPF
STC
POP DI
POP BX
RCCOM: POP DX ; Restore Registers
POP CX
POP AX
RET ; Done
NEXTCLST:
CMP FATSIZE,3 ; If FAT Size = 16 Bits,
JE NEXTCLS1
SHL BX,1 ; Simply Read Next Cluster #
MOV BX,FATBUF[BX]
RET ; Done
NEXTCLS1:
PUSH AX ; Save Registers
PUSH CX
MOV AX,BX ; Word # = Cluster # * 1.5
SHL AX,1
ADD BX,AX
SHR BX,1
MOV BX,FATBUF[BX]
JNC NEXTCLS2 ; If Odd, Use 12 MSB's
MOV CL,4
SHR BX,CL
NEXTCLS2:
AND BX,0FFFH ; Else Use 12 LSB's
POP CX ; Restore Registers
POP AX
RET ; Done
STRIP: LODSB ; Strip Off Leading Whitespace
CMP AL,' '
JE STRIP
CMP AL,9
JE STRIP
OR AL,AL ; If End-of-Parameter, Error
JNZ NOERR1
STC
RET
NOERR1: DEC SI ; ReUse Last Character
MOV OPFLAG,0
MOV DI,OFFSET FSPEC ; Point to FileSpec Buffer
CALL UPPER3
CMP BYTE PTR [SI+1],':' ; If 2nd Character is Colon,
JNE GETPATH
SUB AL,'A' ; Get Drive Number
MOV DRIVE,AL
ADD SI,2 ; and Scan Past
GETPATH:
MOV AL,DRIVE ; Get Drive Number
ADD AL,'A' ; Convert to Drive letter
MOV AH,':' ; and Add Colon
STOSW ; and place in FileSpec
MOV PARMSG+21,AL
MOV FRMSG2+19,AL
CMP BYTE PTR [SI],'\' ; If Next Character is not '\',
JE COPYPATH
MOV AL,'\'
STOSB
PUSH SI ; Get Current Path to FileSpec
MOV SI,DI
MOV AH,47H
MOV DL,DRIVE
INC DL
INT 21H
POP SI
MOV AL,0 ; Find End-of-FileSpec
MOV CX,64
REPNE SCASB
JE NOERR2
JMP ERROR
NOERR2: DEC DI
CMP BYTE PTR [DI-1],'\' ; If Root DIR, Skip
JE COPYPATH
MOV AL,'\' ; End-of-FileSpec = '\'
STOSB
COPYPATH:
LODSB ; Copy Rest of Parameter
CMP AL,'/' ; Until options
JZ GOTOPT
CMP AL,' ' ; Or end of filespec
JZ COPYDONE
OR AL,AL
JZ COPYDONE
STOSB
JMP COPYPATH
GOTOPT: LODSB
CALL UPPER3
TESTOP BFOPAMUV,SETOPT
JMP ERROR
SETOPT: MOV OPFLAG,AH
INC SI
COPYDONE:
DEC SI
MOV AL,0 ; Set End-of-FileSpec
STOSB
MOV DX,OFFSET FSPEC ; Convert to Upper Case
UPPER: PUSH AX ; Save Registers
PUSH DI
PUSH SI
MOV SI,DX ; Set Up Source Index
MOV DI,DX ; Set Up Destination Index
UPPER1: LODSB ; Read From Source
OR AL,AL ; If EOS, Done
JZ UPPER2
CALL UPPER3
STOSB ; Save in Destination
JMP UPPER1 ; Repeat
UPPER2: POP SI ; Restore Registers
POP DI
POP AX
RET ; Done
UPPER3: CMP AL,'a' ; If Lower Case,
JL UPPER4
CMP AL,'z'
JG UPPER4
SUB AL,'a'-'A' ; Convert to Upper Case
UPPER4: RET
OUT_CLST:
PUSH AX ; Save Registers
PUSH DX
PUSH DI
MOV DI,OFFSET CLSTSTR+5 ; Convert Cluster # to Decimal
CALL DEC5OUT
CALL STRIP0 ; Strip Off Leading Zeroes
MOV DI,OFFSET CLSTSTR ; Output Cluster Number
MOV AH,5
OUT_CLS0:
CMP BYTE PTR [DI],' '
JNZ OUT_CLS1
INC DI
DEC AH
JMP OUT_CLS0
OUT_CLS1:
MOV DX,DI
CALL DOS9
POP DI ; Restore Registers
POP DX
POP AX
RET ; Done
STRIP0: CMP BYTE PTR [DI],'0' ; If Character != '0', Done
JNE STRIP1
CMP BYTE PTR [DI+1],'0' ; If Next Character != Digit,
JL STRIP1 ; Done
CMP BYTE PTR [DI+1],'9'
JG STRIP1
MOV BYTE PTR [DI],' ' ; Change '0' to ' '
INC DI ; Point to Next Character
JMP STRIP0 ; Repeat
STRIP1: RET ; Done
DEC2OUT:
PUSH AX ; Save Registers
PUSH BX
D2O1: XOR AH,AH ; Clear AH
MOV BL,10 ; AH=AX%10,AL=AX/10
DIV BL
ADD AX,'00' ; Convert to ASCII
SUB DI,2
MOV [DI],AX ; Store in String
POP BX ; Restore Registers
POP AX
RET ; Done
DEC4OUT:
PUSH AX ; Save Registers
PUSH BX
D4O1: MOV BL,100 ; AH=AX%100,AL=AX/100
DIV BL
XCHG AH,AL ; Convert 2 LSD's
CALL DEC2OUT
XCHG AH,AL ; Convert 2 MSD's
JMP D2O1 ; Using common code
DEC5OUT:
PUSH AX ; Save Registers
PUSH BX
PUSH DX ; DX=AX%10000,AX=AX/10000
MOV BX,10000
XOR DX,DX
DIV BX
XCHG DX,AX ; Convert 4 LSD's
CALL DEC4OUT
ADD DL,'0' ; Convert MSD
DEC DI
MOV [DI],DL
POP DX ; Restore Registers
POP BX
POP AX
RET ; Done
DEC8OUT:
PUSH AX ; Save Registers
PUSH BX
PUSH DX
MOV BX,10000 ; DX=DX:AX%10000,AX=DX:AX/10000
DIV BX
XCHG DX,AX ; Convert 4 LSD's
CALL DEC4OUT
XCHG DX,AX ; Convert 4 MSD's
POP DX
JMP D4O1 ; Using common code
TABLE LABEL WORD
FATBUF EQU TABLE+8192
CODE ENDS
END CHAIN
vert 4 MSD's
POP DX
JMP D4O1 ; Using common code
TABLE LABEL WORD
FATBUF EQU TABLE+8192
COD